#include "../Base.h"

HANDLE handle;
PKDPC timerDpc;
extern PKTIMER timer;
VOID
DefaultDpcRoutine(
	_In_ struct _KDPC* Dpc,
	_In_opt_ PVOID DeferredContext,
	_In_opt_ PVOID SystemArgument1,
	_In_opt_ PVOID SystemArgument2
) {
	LOG("Default dpc routine   processor = %d;irql = %d;", KeGetCurrentProcessorNumber(), KeGetCurrentIrql());
}

NTSTATUS InsertDpcTimer(KDEFERRED_ROUTINE func, PVOID context, ULONG_PTR delayTime, ULONG_PTR circleTime) {
	NTSTATUS status = STATUS_UNSUCCESSFUL;

	timerDpc = (PKDPC)ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), 'yang');

	timer = (PKTIMER)ExAllocatePoolWithTag(NonPagedPool, sizeof(KTIMER), 'yang');

	if (!func) {
		KeInitializeDpc(timerDpc, DefaultDpcRoutine, NULL);
	}
	else {
		KeInitializeDpc(timerDpc, func, context);
	}

	KeInitializeTimerEx(timer, SynchronizationTimer);

	LARGE_INTEGER time;

	time.QuadPart = -10000 * delayTime;

	if (!KeSetTimerEx(timer, time, circleTime, timerDpc)) {
		return status;
	}

	status = STATUS_SUCCESS;

	return status;
}

VOID UnInsertDpcTimer() {

	if (timer) {
		KeCancelTimer(timer);
		ExFreePoolWithTag(timer, 'yang');
	}
	if (timerDpc) {

		ExFreePoolWithTag(timerDpc, 'yang');
	}
}

VOID
DefaultApcRoutine(
	_In_ PVOID TimerContext,
	_In_ ULONG TimerLowValue,
	_In_ LONG TimerHighValue
) {

	LOG("Default APC routine   processor = %d;irql = %d;", KeGetCurrentProcessorNumber(), KeGetCurrentIrql());
	
}

NTSTATUS InsertUserTimer(PTIMER_APC_ROUTINE func, PVOID context, ULONG_PTR delayTime, ULONG_PTR circleTime) {
	NTSTATUS status = ZwCreateTimer(&handle, PROCESS_ALL_ACCESS, NULL, SynchronizationTimer);
	if (!NT_SUCCESS(status)) {
		LOG("ZwCreateTimer失败");
		return status;
	}

	LARGE_INTEGER time;

	time.QuadPart = -10000 * 1000;

	status = ZwSetTimer(handle, &time, DefaultApcRoutine, NULL, FALSE, 1000, NULL);
	if (!NT_SUCCESS(status)) {
		LOG("ZwSetTimer失败");
	}
	return status;
}

VOID UnInsertUserTimer() {
	if (handle) {
		ZwCancelTimer(handle, NULL);
		ZwClose(handle);
	}
}